<template>
  <div class="app-contanier" :class="$isMobile ? '' : 'player-pc'">
    <div class="video-player">
      <template v-if="isLive">
        <div class="default-content live-container" v-if="state === '0'">
          <div class="place-content">
            <van-divider>直播未开始</van-divider>
            <van-count-down v-if="countTime > 0" :time="countTime">
              <template #default="timeData">
                <span class="time-head">距离开始:</span>
                <span class="block" v-if="timeData.days">{{
                  timeData.days
                }}</span>
                <span class="colon" v-if="timeData.days">天</span>
                <span class="block" v-if="timeData.hours">{{
                  timeData.hours
                }}</span>
                <span class="colon" v-if="timeData.hours">时</span>
                <span class="block" v-if="timeData.minutes">{{
                  timeData.minutes
                }}</span>
                <span class="colon" v-if="timeData.minutes">分</span>
                <span class="block" v-if="timeData.seconds">{{
                  timeData.seconds
                }}</span>
                <span class="colon" v-if="timeData.seconds">秒</span>
              </template>
            </van-count-down>
          </div>
        </div>
        <div class="default-content end-container" v-else-if="state === '2'">
          <div class="place-content">
            <van-divider>直播暂停中</van-divider>
          </div>
        </div>
        <div class="default-content end-container" v-else-if="state === '3'">
          <div class="place-content">
            <van-divider>直播已结束</van-divider>
          </div>
        </div>
        <template v-else>
          <div
            v-if="videoUrl"
            class="player-container live-player"
            id="player-container"
            ref="playerRef"
          ></div>
          <div class="default-content end-container" v-else>
            <div class="place-content" v-if="isInitUrl">
              <van-divider>直播地址不存在</van-divider>
            </div>
          </div>
        </template>
      </template>
      <template v-else>
        <div
          v-if="videoUrl"
          class="player-container"
          id="player-container"
          ref="playerRef"
        ></div>
        <div class="default-content end-container" v-else>
          <div class="place-content" v-if="isInitUrl">
            <van-divider>视频地址不存在</van-divider>
          </div>
        </div>
      </template>
    </div>

    <div class="video-msg-content">
      <div class="detail-content video-content">
        <div class="title">{{ title }}</div>
        <div class="desc">{{ desc }}</div>
        <div class="num">
          <i class="sdlive icon-dianzan_kuai"></i>
          <span>{{ likeNum }}</span>
          <i class="sdlive icon-sc-active"></i>
          <span>{{ collectNum }}</span>
        </div>
      </div>
      <!--分集-->
      <div class="video-list" v-if="!isLive && videoList.length">
        <template v-if="$isMobile">
          <van-tabs
            v-model:active="videoCurrentIndex"
            @change="videChange"
            shrink
          >
            <van-tab
              v-for="(item, index) in videoList"
              :key="`video_${index + 1}`"
              :title="`第${index + 1}集`"
            ></van-tab>
          </van-tabs>
        </template>
        <template v-else>
          <div
            v-for="(item, index) in videoList"
            :key="`video_${index + 1}`"
            :class="[
              'video-number',
              videoCurrentIndex === index ? 'active' : '',
            ]"
            @click="videChange(index)"
          >
            {{ `第${index + 1}集` }}
          </div>
        </template>
      </div>
      <!--点赞 分享 收藏-->
      <div :class="['video-operate', $isMobile ? 'mobile': '']">
        <div class="operate" @click="likeItem">
          <div
            :class="[
              'operate-icon operate-like sdlive',
              isLike ? 'icon-dianzan_kuai' : 'icon-dianzan',
            ]"
          ></div>
        </div>
        <div class="operate" @click="collectItem">
          <div
            :class="[
              'operate-icon operate-sc sdlive',
              isCollect ? 'icon-sc-active' : 'icon-sc',
            ]"
          ></div>
        </div>
        <div class="operate" @click="share">
          <div class="operate-icon operate-share sdlive icon-share-s"></div>
        </div>
      </div>
      <!-- 回复 -->
      <CommentList
        v-if="isLive"
        ref="commentRef"
        :id="detailId"
        :live-id="liveId"
      />
    </div>
  </div>
  <!--提示输入-->
  <InputPwd
    ref="inputPwdRef"
    :password="password"
    :show-cancel="false"
    @pass="passPwd"
  />
</template>

<script setup>
import { nextTick, onBeforeUnmount, onMounted, ref, inject } from 'vue'
import { useRoute, useRouter } from 'vue-router'
import dayjs from 'dayjs'

import Player from 'xgplayer'
import FlvPlugin from 'xgplayer-flv'

import InputPwd from '@/components/input-pwd.vue'
import CommentList from './comment-list.vue'

import { useAuthStore } from '@/store/auth'

import { VantMessage } from '@/utils/vant-utils'
import { WEB_HREF } from '@/utils/index'
import { wxShare } from '@/utils/wx'
import { sm2Decrypt } from '@/utils/sm2'

import { useSocket } from '@/hooks/useSocket'

import {
  getInfo,
  likeCount,
  collectCount,
  likeCheck,
  collectCheck,
  likeLive,
  collectLive,
  getLiveUrls
} from '@/api/live'

import {
  getDemandInfo,
  likeDemand,
  demandLikeCount,
  demandLikeCheck,
  collectDemand,
  demandCollectCount,
  demandCollectCheck,
  getDemandUrls
} from '@/api/demand'

const $router = useRouter()
const $route = useRoute()
const authStore = useAuthStore()
const inputPwdRef = ref(null)

const isMobile = inject('isMobile')

const props = defineProps({
  id: {
    type: String,
    default: ''
  },
  isLive: {
    type: Boolean,
    default: true
  }
})

const playerRef = ref(null)
let videoPlayer = null // 播放器

const detailId = ref('')

const videoUrl = ref('')
const videoList = ref([])
const videoCurrentIndex = ref(0)

const title = ref('')
const desc = ref('')
const password = ref('')
const liveId = ref('')

const likeNum = ref(0)
const collectNum = ref(0)
const state = ref('1')
const countTime = ref(0)

const isLike = ref(false)
const isCollect = ref(false)

const likeDisable = ref(false)
const collectDisable = ref(false)

const isPassPwd = ref(false) // 是否已经通过输入
const isInitUrl = ref(false) // 是否已经加载url

const commentRef = ref(null)

const wsUrl = ref('')

const videoInit = async() => {
  await nextTick()
  if (!videoUrl.value || !playerRef.value) {
    return
  }
  if (!videoPlayer) {
    const config = {
      id: 'player-container',
      playsinline: true,
      plugins: [],
      autoplay: true,
      closeVideoTouch: true,
      url: videoUrl.value,
      isLive: props.isLive,
      width: playerRef.value.clientWidth,
      pip: true,
      cssFullscreen: false,
      'x5-video-player-type': 'h5',
      'x5-video-player-fullscreen': 'true',
      'x5-video-orientation': 'landscape'
    }
    if (isMobile) {
      // config.mini = true
      config.fitVideoSize = 'fixWidth'
    } else {
      config['height'] = playerRef.value.clientHeight
      config.fitVideoSize = 'fixWidth'
      config.videoFillMode = 'fillHeight'
      config.fluid = true
    }
    if (props.isLive) {
      config.plugins.push(FlvPlugin)
      // 直播移除倍数
      config.playbackRate = [null]
    }
    videoPlayer = new Player(config)
  } else {
    videoPlayer.playNext({
      url: videoUrl.value
    })
  }
  videoPlayer.play()
}

// 切换视频
const videChange = (index) => {
  videoUrl.value = videoList.value[index].url
  videoCurrentIndex.value = index
  videoInit()
}

// 直播详情
const getLiveInfo = async(id) => {
  try {
    const infoRes = await getInfo(id)
    if (infoRes.data) {
      const info = infoRes.data
      title.value = info.title
      // TODO: 改成后台state info.liveState
      state.value = info.liveState
      desc.value = info.briefIntroduction
      // 密码
      password.value = sm2Decrypt(info.meetingPassword)
      // 倒计时
      if (state.value === '0') {
        countTime.value =
          dayjs(info.startTime).toDate().getTime() - new Date().getTime()
      }
      // 获取点赞收藏
      getLiveLC(id)
      // 已经通过的去请求属性当前链接
      if (isPassPwd.value) {
        passPwd()
      } else {
        // 如果输入正常过来直接拿去地址
        if ($route.query.pass && $route.query.pass === '1') {
          passPwd()
        } else {
          if (inputPwdRef.value) {
            inputPwdRef.value.toShowDialog(true)
          }
        }
      }
      // 进行获取留言
      if (commentRef.value) {
        commentRef.value.getList()
      }
      liveId.value = info.liveId
      // 刷新当前
      if (state.value !== '3') {
        //   未开启刷新的进入刷新
        refreshLive()
      }
    } else {
      VantMessage.error('直播不存在')
      $router.go(-1)
    }
  } catch (error) {
    console.log('error', error)
    VantMessage.error('获取直播详情失败')
  }
}

const msgHandler = (msg) => {
  if (!(msg && msg.liveId && msg.liveId === liveId.value)) {
    return
  }
  const type = msg.type
  if (type === 'state') {
    // 如果当前状态不是直播中，但是后台返回直播中状态后，重新刷新状态
    console.log('player liveState >>>', msg.liveState)
    if (state.value !== '1' && msg.liveState === '1') {
      state.value = msg.liveState
      if (isPassPwd.value) {
        videoInit()
      }
    } else {
      // 其他状态删除 player
      videoPlayer = null
      state.value = msg.liveState
    }
  } else if (type === 'comment') {
    if (commentRef.value && msg.liveComment) {
      // 添加消息
      commentRef.value.pushComment(msg.liveComment)
    }
  }
}

const refreshLive = () => {
  wsUrl.value = `${window.env.VUE_APP_STATE_SCOKET}/${liveId.value}?userId=${authStore.userId}`
  initSocket()
}

// 验证密码成功
const passPwd = async() => {
  isPassPwd.value = true
  // 如果已经有url啦不需要
  if (videoUrl.value) {
    return
  }
  await nextTick()
  // 获取视频链接 初始化视频
  try {
    const urlRes = await getLiveUrls(detailId.value)
    // 是否已经加载过url啦
    if (!isInitUrl.value) {
      isInitUrl.value = true
    }
    if (urlRes.data && urlRes.data instanceof Array && urlRes.data.length) {
      videoUrl.value = urlRes.data[0].videoFlv
      videoInit()
    }
  } catch (error) {
    isInitUrl.value = false
  }
}
// 获取直播的点赞收藏
const getLiveLC = async(id) => {
  try {
    // 获取点赞及数量
    const likeRes = await likeCount(id)
    const collectRes = await collectCount(id)
    likeNum.value = likeRes.data || 0
    collectNum.value = collectRes.data || 0
    // 获取当前用户是否点赞
    const checkLike = await likeCheck(id)
    const checkCollect = await collectCheck(id)
    isLike.value = checkLike.data || false
    isCollect.value = checkCollect.data || false
  } catch (error) {
    VantMessage.error('网络异常')
  }
}

// 点播详情
const demandInfo = async(id) => {
  try {
    const infoRes = await getDemandInfo(id)
    if (infoRes.data) {
      const info = infoRes.data
      title.value = info.title
      desc.value = info.briefIntroduction
      // 获取点赞收藏
      getDemandLC(id)
      // 获取视频链接， 初始化视频
      const urlRes = await getDemandUrls(id)
      if (urlRes.data && urlRes.data instanceof Array && urlRes.data.length) {
        videoList.value = urlRes.data.map((item, index) => ({
          name: `video_${index + 1}`,
          url: item.url
        }))
        videoUrl.value = videoList.value[0].url
        videoCurrentIndex.value = 0
        videoInit()
      }
    } else {
      VantMessage.error('视频不存在')
      $router.go(-1)
    }
  } catch (error) {
    VantMessage.error('获取视频详情失败')
  }
}

// 获取点播的点赞收藏
const getDemandLC = async(id) => {
  try {
    // 获取点赞及数量
    const likeRes = await demandLikeCount(id)
    const collectRes = await demandCollectCount(id)
    likeNum.value = likeRes.data || 0
    collectNum.value = collectRes.data || 0
    // 获取当前用户是否点赞
    const checkLike = await demandLikeCheck(id)
    const checkCollect = await demandCollectCheck(id)
    isLike.value = checkLike.data || false
    isCollect.value = checkCollect.data || false
  } catch (error) {
    VantMessage.error('网络异常')
  }
}

// 点赞
const likeItem = async() => {
  if (!detailId.value) {
    return
  }
  try {
    isLike.value = !isLike.value
    const diffNum = isLike.value ? 1 : -1
    const currentNum = likeNum.value + diffNum
    likeNum.value = currentNum <= 0 ? 0 : currentNum
    if (likeDisable.value) {
      return
    }
    // 点赞程序
    likeDisable.value = true
    if (props.isLive) {
      // 直播
      await likeLive(detailId.value, !isLike.value)
    } else {
      // 点播
      await likeDemand(detailId.value, !isLike.value)
    }
    likeDisable.value = false
  } catch (error) {
    likeDisable.value = false
    VantMessage.error('点赞失败')
  }
}

// 收藏
const collectItem = async() => {
  if (!detailId.value) {
    return
  }
  try {
    isCollect.value = !isCollect.value
    const diffNum = isCollect.value ? 1 : -1
    const currentNum = collectNum.value + diffNum
    collectNum.value = currentNum <= 0 ? 0 : currentNum
    if (collectDisable.value) {
      return
    }
    // 收藏数据
    collectDisable.value = true
    if (props.isLive) {
      // 直播
      await collectLive(detailId.value, !isCollect.value)
    } else {
      // 点播
      await collectDemand(detailId.value, !isCollect.value)
    }
    collectDisable.value = false
  } catch (error) {
    collectDisable.value = false
    VantMessage.error('收藏失败')
  }
}

const initPage = async() => {
  await nextTick()
  const id = $route.query && $route.query.id
  if (!id) {
    return
  }
  detailId.value = id
  // TODO: 获取详情
  if (props.isLive) {
    // 获取直播详情
    getLiveInfo(id)
  } else {
    // 获取点播详情
    demandInfo(id)
  }
}

const share = () => {
  wxShare(
    {
      title: title.value,
      desc: desc.value,
      link: `${WEB_HREF}/${props.isLive ? 'live-detail' : 'video-detail'}?id=${
        detailId.value
      }`
    },
    props.isLive
  )
}

// eslint-disable-next-line prefer-const
let { colseSocket, initSocket } = useSocket(wsUrl, msgHandler)

onMounted(async() => {
  initPage()
})

onBeforeUnmount(() => {
  colseSocket()
  // 销毁播放器
  if (videoPlayer && videoPlayer.destroy) {
    videoPlayer.destroy()
    videoPlayer = null
  }
})
</script>

<style lang="less" scoped src="@/styles/player.less"></style>
